﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using Newtonsoft.Json;
using IPC.Communication.Framework.Reflection;

namespace IPC.Communication.Framework
{
    public class HslTimeOut
    {
        private static long hslTimeoutId;

        private static List<HslTimeOut> WaitHandleTimeOut;

        private static object listLock;

        private static Thread threadCheckTimeOut;

        private static long threadUniqueId;

        private static DateTime threadActiveTime;

        private static int activeDisableCount;

        public long UniqueId
        {
            get;
            private set;
        }

        public DateTime StartTime
        {
            get;
            set;
        }

        public bool IsSuccessful
        {
            get;
            set;
        }

        public int DelayTime
        {
            get;
            set;
        }

        [JsonIgnore]
        public Socket WorkSocket
        {
            get;
            set;
        }

        public bool IsTimeout
        {
            get;
            set;
        }

        [HslMqttApi(Description = "Get the number of current check timeout objects", HttpMethod = "GET")]
        public static int TimeOutCheckCount
        {
            get
            {
                return HslTimeOut.WaitHandleTimeOut.Count;
            }
        }

        public HslTimeOut()
        {
            this.UniqueId = Interlocked.Increment(ref HslTimeOut.hslTimeoutId);
            this.StartTime = DateTime.Now;
            this.IsSuccessful = false;
            this.IsTimeout = false;
        }

        public TimeSpan GetConsumeTime()
        {
            return DateTime.Now - this.StartTime;
        }

        public override string ToString()
        {
            return string.Format("HslTimeOut[{0}]", this.DelayTime);
        }

        public static void HandleTimeOutCheck(HslTimeOut timeOut)
        {
            object obj = HslTimeOut.listLock;
            lock (obj)
            {
                bool flag2 = (DateTime.Now - HslTimeOut.threadActiveTime).TotalSeconds > 60.0;
                if (flag2)
                {
                    HslTimeOut.threadActiveTime = DateTime.Now;
                    bool flag3 = Interlocked.Increment(ref HslTimeOut.activeDisableCount) >= 2;
                    if (flag3)
                    {
                        HslTimeOut.CreateTimeoutCheckThread();
                    }
                }
                HslTimeOut.WaitHandleTimeOut.Add(timeOut);
            }
        }

        [HslMqttApi(Description = "Get the current list of all waiting timeout check objects, do not manually change the property value of the object", HttpMethod = "GET")]
        public static HslTimeOut[] GetHslTimeOutsSnapShoot()
        {
            object obj = HslTimeOut.listLock;
            HslTimeOut[] result;
            lock (obj)
            {
                result = HslTimeOut.WaitHandleTimeOut.ToArray();
            }
            return result;
        }

        public static HslTimeOut HandleTimeOutCheck(Socket socket, int timeout)
        {
            HslTimeOut hslTimeOut = new HslTimeOut
            {
                DelayTime = timeout,
                IsSuccessful = false,
                StartTime = DateTime.Now,
                WorkSocket = socket
            };
            bool flag = timeout > 0;
            if (flag)
            {
                HslTimeOut.HandleTimeOutCheck(hslTimeOut);
            }
            return hslTimeOut;
        }

        static HslTimeOut()
        {
            HslTimeOut.hslTimeoutId = 0L;
            HslTimeOut.WaitHandleTimeOut = new List<HslTimeOut>(128);
            HslTimeOut.listLock = new object();
            HslTimeOut.threadUniqueId = 0L;
            HslTimeOut.activeDisableCount = 0;
            HslTimeOut.CreateTimeoutCheckThread();
        }

        private static void CreateTimeoutCheckThread()
        {
            HslTimeOut.threadActiveTime = DateTime.Now;
            Thread expr_10 = HslTimeOut.threadCheckTimeOut;
            if (expr_10 != null)
            {
                expr_10.Abort();
            }
            HslTimeOut.threadCheckTimeOut = new Thread(new ParameterizedThreadStart(HslTimeOut.CheckTimeOut));
            HslTimeOut.threadCheckTimeOut.IsBackground = true;
            HslTimeOut.threadCheckTimeOut.Priority = ThreadPriority.AboveNormal;
            HslTimeOut.threadCheckTimeOut.Start(Interlocked.Increment(ref HslTimeOut.threadUniqueId));
        }

        private static void CheckTimeOut(object obj)
        {
            long num = (long)obj;
            while (true)
            {
                Thread.Sleep(100);
                bool flag = num != HslTimeOut.threadUniqueId;
                if (flag)
                {
                    break;
                }
                HslTimeOut.threadActiveTime = DateTime.Now;
                HslTimeOut.activeDisableCount = 0;
                object obj2 = HslTimeOut.listLock;
                lock (obj2)
                {
                    for (int i = HslTimeOut.WaitHandleTimeOut.Count - 1; i >= 0; i--)
                    {
                        HslTimeOut hslTimeOut = HslTimeOut.WaitHandleTimeOut[i];
                        bool isSuccessful = hslTimeOut.IsSuccessful;
                        if (isSuccessful)
                        {
                            HslTimeOut.WaitHandleTimeOut.RemoveAt(i);
                        }
                        else
                        {
                            bool flag3 = (DateTime.Now - hslTimeOut.StartTime).TotalMilliseconds > (double)hslTimeOut.DelayTime;
                            if (flag3)
                            {
                                bool flag4 = !hslTimeOut.IsSuccessful;
                                if (flag4)
                                {
                                    Socket expr_CE = hslTimeOut.WorkSocket;
                                    if (expr_CE != null)
                                    {
                                        expr_CE.Close();
                                    }
                                    hslTimeOut.IsTimeout = true;
                                }
                                HslTimeOut.WaitHandleTimeOut.RemoveAt(i);
                            }
                        }
                    }
                }
            }
        }
    }
}
